<!DOCTYPE html>
<html lang="zh-CN">


<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta name="author" content="viggo" />
  <title>MrLiu的博客 - </title>
  <meta name="keywords" content="">
  <meta name="description" content="">
  <link rel="shortcut icon" href="/static/favicon.ico">
  <link rel="stylesheet" href="/css/github.min.css">
  <script src="/js/highlight.min.js"></script>
  
<link rel="stylesheet" href="//fonts.loli.net/css?family=Arimo:400,700,400italic.css">
<link rel="stylesheet" href="/css/fonts/linecons/css/linecons.min.css">
<link rel="stylesheet" href="/css/fonts/fontawesome/css/all.min.css">
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/xenon-core.min.css">
<link rel="stylesheet" href="/css/xenon-components.min.css">
<link rel="stylesheet" href="/css/xenon-skins.min.css">
<link rel="stylesheet" href="/css/index.css">
<link rel="stylesheet" href="/css/nav.min.css">
<link rel="stylesheet" href="/css/md.css">

  
<script src="/js/jquery-1.11.1.min.js"></script>

  
<script src="/js/header.js"></script>

  <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
  <!--[if lt IE 9]>
        
<script src="/js/html5shiv.min.js"></script>

        
<script src="/js/respond.min.js"></script>

    <![endif]-->
  <script>
  hljs.configure({useBR: true});
  hljs.initHighlightingOnLoad();
  </script>
  <!-- / FB Open Graph -->
  <meta property="og:type" content="article">
  <meta property="og:url" content="https://liu-meizhou.github.io/js%E5%8E%9F%E5%9E%8B%E9%93%BE/index.html">
  <meta property="og:title" content="MrLiu的博客 - ">
  <meta property="og:description" content="">
  <meta property="og:site_name" content="MrLiu的博客 - ">
  
  <meta property="og:image" content="/images/webstack_banner_cn.png">
  
  <!-- / Twitter Cards -->
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:title" content="MrLiu的博客 - ">
  <meta name="twitter:description" content="">
  
  <meta name="twitter:image" content="/images/webstack_banner_cn.png">
  
<meta name="generator" content="Hexo 5.4.0"></head>

<body>
  <div class="page-container">
    <div class="sidebar-menu toggle-others fixed">
  <div class="sidebar-menu-inner">
    <header class="logo-env">
      <div class="logo">
        <a href="/index.html" class="logo-expanded">
          <img src="/images/logo@2x.png" width="100%" alt="" />
        </a>
        <a href="/index.html" class="logo-collapsed">
          <img src="/images/logo-collapsed@2x.png" width="40" alt="" />
        </a>
      </div>
      <div class="mobile-menu-toggle visible-xs">
        <a href="#" data-toggle="user-info-menu">
          <i class="linecons-cog"></i>
        </a>
        <a href="#" data-toggle="mobile-menu">
          <i class="fas fa-bars"></i>
        </a>
      </div>
    </header>
    <ul id="main-menu" class="main-menu">
      

      
        <li><a href="#PWA" class="smooth" style="padding-left: 0em" title="PWA"><i class="far fa-star"></i><span class="title">PWA</span></a></li><li><a href="#打包和拆分" class="smooth" style="padding-left: 0em" title="打包和拆分"><i class="far fa-star"></i><span class="title">打包和拆分</span></a></li><li><a href="#阻塞渲染的资源" class="fas fa-angle-down" style="cursor: pointer; padding-left: 0em" title="阻塞渲染的资源"><i class="far fa-star"></i><span class="title">阻塞渲染的资源</span></a><ul><li><a href="#解决办法" class="fas fa-angle-down" style="cursor: pointer; padding-left: 1em" title="解决办法"><i class="far fa-star"></i><span class="title">解决办法</span></a><ul><li><a href="#css" class="smooth" style="padding-left: 2em" title="css"><i class="far fa-star"></i><span class="title">css</span></a></li><li><a href="#js" class="smooth" style="padding-left: 2em" title="js"><i class="far fa-star"></i><span class="title">js</span></a></li><li><a href="#图片" class="smooth" style="padding-left: 2em" title="图片"><i class="far fa-star"></i><span class="title">图片</span></a></li></ul></li></ul></li><li><a href="#应用框架" class="fas fa-angle-down" style="cursor: pointer; padding-left: 0em" title="应用框架"><i class="far fa-star"></i><span class="title">应用框架</span></a><ul><li><a href="#服务器渲染-SSR" class="smooth" style="padding-left: 1em" title="服务器渲染-SSR"><i class="far fa-star"></i><span class="title">服务器渲染-SSR</span></a></li><li><a href="#客户端渲染-CSR" class="smooth" style="padding-left: 1em" title="客户端渲染-CSR"><i class="far fa-star"></i><span class="title">客户端渲染-CSR</span></a></li><li><a href="#混合渲染" class="fas fa-angle-down" style="cursor: pointer; padding-left: 1em" title="混合渲染"><i class="far fa-star"></i><span class="title">混合渲染</span></a><ul><li><a href="#App-Shell" class="smooth" style="padding-left: 2em" title="App Shell"><i class="far fa-star"></i><span class="title">App Shell</span></a></li></ul></li></ul></li>
      

      
      <li class="submit-tag">
        <a href="/author">
          <i class="far fa-heart"></i>
          <span class="tooltip-blue">关于作者</span>
        </a>
      </li>
      
      
      <li>
        <a href="javascript:void(0)">
          <i class="fas fa-eye"></i>
          <span id="busuanzi_container_site_pv">本站总访问量<span id="busuanzi_value_site_pv"></span></span>
        </a>
      </li>
      <li>
        <a href="javascript:void(0)">
          <i class="fas fa-users"></i>
          <span id="busuanzi_container_site_uv">本站总访客数<span id="busuanzi_value_site_uv"></span></span>
        </a>
      </li>
      
    </ul>
  </div>
  <div class="e-resize"></div>
</div>

    <div class="main-content">
      <nav class="navbar user-info-navbar" role="navigation">
        <ul class="user-info-menu left-links list-inline list-unstyled">
          <li class="hidden-sm hidden-xs hover-line">
            <a href="#" data-toggle="sidebar">
              <i class="fas fa-bars"></i>
            </a>
          </li>
          <li class="dropdown hover-line language-switcher">
            <a href="/index.html" class="dropdown-toggle" data-toggle="dropdown">
              <img src="/images/flags/flag-cn.png" alt="flag-cn" /> Chinese
            </a>
            <ul class="dropdown-menu languages">
              <li class="active">
                <a href="/index.html">
                  <img src="/images/flags/flag-cn.png" alt="flag-cn" alt="flag-cn" /> Chinese
                </a>
              </li>
            </ul>
          </li>
          <li class="switch-mode hover-line" onclick="switchNightMode()">
            <a href="#">
              <svg t="1593061068148" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1681" width="16" height="16">
                <path d="M582.4 326.4c-140.8 0-256 115.2-256 256s115.2 256 256 256 256-115.2 256-256-115.2-256-256-256z m0 448c-70.4 0-131.2-36.8-164.8-92.8 12.8 3.2 27.2 4.8 40 4.8 121.6 0 219.2-99.2 219.2-219.2 0-17.6-1.6-35.2-6.4-52.8 60.8 32 102.4 96 102.4 169.6 1.6 104-84.8 190.4-190.4 190.4zM582.4 262.4c17.6 0 32-14.4 32-32v-128c0-17.6-14.4-32-32-32s-32 14.4-32 32v128c0 17.6 14.4 32 32 32zM262.4 582.4c0-17.6-14.4-32-32-32h-128c-17.6 0-32 14.4-32 32s14.4 32 32 32h128c17.6 0 32-14.4 32-32zM310.4 356.8c6.4 6.4 14.4 9.6 22.4 9.6 8 0 16-3.2 22.4-9.6 12.8-12.8 12.8-32 0-44.8l-91.2-91.2c-12.8-12.8-32-12.8-44.8 0-12.8 12.8-12.8 32 0 44.8l91.2 91.2zM944 220.8c-12.8-12.8-32-12.8-44.8 0l-91.2 91.2c-12.8 12.8-12.8 32 0 44.8 6.4 6.4 14.4 9.6 22.4 9.6 8 0 16-3.2 22.4-9.6l91.2-91.2c12.8-12.8 12.8-33.6 0-44.8zM310.4 808l-91.2 91.2c-12.8 12.8-12.8 32 0 44.8 6.4 6.4 14.4 9.6 22.4 9.6 8 0 16-3.2 22.4-9.6l91.2-91.2c12.8-12.8 12.8-32 0-44.8-11.2-11.2-32-11.2-44.8 0z" p-id="1682" fill="#707070"></path>
              </svg>
            </a>
          </li>
        </ul>
        
        <a target="_blank" rel="noopener" href="https://github.com/liu-meizhou/liu-meizhou.github.io" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
        
      </nav>
      
<h1 id="PWA"><a href="#PWA" class="headerlink" title="PWA"></a>PWA</h1><p>PWA（Progressive Web Apps，渐进式 Web 应用）<br>可离线访问的web应用 - 就是<strong>web应用和电脑app的结合体</strong></p>
<ul>
<li>可发现、可链接：通过web搜索</li>
<li>可安装：不需要依赖浏览器，可出现在设备主屏</li>
<li>独立于网络：离线或网络差也可访问</li>
<li>渐进式：老版浏览器可使用，新版可使用全部功能</li>
<li>可重入：无论何时有新内容，都可发生通知</li>
<li>响应式：设配手机、平板电脑、笔记本、显示器</li>
<li>安全：https协议，防止中间人嗅探</li>
</ul>
<h1 id="打包和拆分"><a href="#打包和拆分" class="headerlink" title="打包和拆分"></a>打包和拆分</h1><p>通常加载一个较大打包后的文件会比加载很多小文件要快一些，但如果用户并不是一开始就需要所有资源，就没必要一次性传输太大文件，拆分文件，惰性加载，让用户更快看到界面。css结构定义各个版本的样式：移动端、平板、桌面、打印版</p>
<h1 id="阻塞渲染的资源"><a href="#阻塞渲染的资源" class="headerlink" title="阻塞渲染的资源"></a>阻塞渲染的资源</h1><p>浏览器在把计算结果渲染到屏幕之前，需要先把HTML、css、JavaScript下载下来。在页面被打开到加载完成的这段时间里，用户将会看到一个空白页</p>
<h2 id="解决办法"><a href="#解决办法" class="headerlink" title="解决办法"></a>解决办法</h2><h3 id="css"><a href="#css" class="headerlink" title="css"></a>css</h3><ul>
<li><p>给css加上media属性</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-comment">&lt;!-- 加上media的css文件会在对应媒体类型下载，否则不下载 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">&quot;stylesheet&quot;</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;print.css&quot;</span> <span class="hljs-attr">media</span>=<span class="hljs-string">&quot;print&quot;</span> /&gt;</span><br><span class="hljs-comment">&lt;!-- 注：css直接放在style会提升应用性能，但可读性降低，一般不选择这样做 --&gt;</span><br></code></pre></td></tr></table></figure></li>
</ul>
<h3 id="js"><a href="#js" class="headerlink" title="js"></a>js</h3><ul>
<li><p>在script标签上面加上一个defer</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-comment">&lt;!-- 加上defer的脚本文件会等到文档解析完成之后再开始下载和执行 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">&quot;app.js&quot;</span> <span class="hljs-attr">defer</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br></code></pre></td></tr></table></figure></li>
</ul>
<h3 id="图片"><a href="#图片" class="headerlink" title="图片"></a>图片</h3><ul>
<li><p>使用更轻量级、体积更小的图片作为img的占位符</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-comment">&lt;!-- src作为占位符 使用data-src属性作为正在图片位置 --&gt;</span><br><span class="hljs-comment">&lt;!-- data-src会等网站构建完HTML主体框架之后通过JavaScript进行加载 --&gt;</span><br><span class="hljs-comment">&lt;!-- data-src的图片会占原有图片的宽高，所有正在图片加载后不会导致重绘 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">&quot;placeholder.png&quot;</span> <span class="hljs-attr">data-src</span>=<span class="hljs-string">&quot;data.jpg&quot;</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">&quot;NAME&quot;</span> /&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">// 通过js加载data-src</span><br><span class="hljs-keyword">let</span> imagesToLoad = <span class="hljs-built_in">document</span>.querySelectorAll(<span class="hljs-string">&#x27;img[data-src]&#x27;</span>);<br><span class="hljs-keyword">const</span> loadImages = <span class="hljs-function">(<span class="hljs-params">image</span>) =&gt;</span> &#123;<br>    image.setAttribute(<span class="hljs-string">&#x27;src&#x27;</span>, image.getAttribute(<span class="hljs-string">&#x27;data-src&#x27;</span>));<br>    image.onload = <span class="hljs-function">() =&gt;</span> &#123;<br>        image.removeAttribute(<span class="hljs-string">&#x27;data-src&#x27;</span>);<br>    &#125;<br>&#125;<br><span class="hljs-comment">// 在页面主体框架加载之后</span><br>imagesToLoad.forEach(<span class="hljs-function">(<span class="hljs-params">img</span>) =&gt;</span> &#123;<br>    loadImages(img);<br>&#125;);<br></code></pre></td></tr></table></figure>

<ul>
<li>为了这个占位图片加载效果更好，使用css模糊处理</li>
</ul>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs css"><span class="hljs-selector-tag">img</span><span class="hljs-selector-attr">[data-src]</span> &#123;<br>	<span class="hljs-attribute">filter</span>: <span class="hljs-built_in">blur</span>(<span class="hljs-number">0.2em</span>);<br>&#125;<br><span class="hljs-selector-tag">img</span> &#123;<br>    <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">blur</span>(<span class="hljs-number">0em</span>);<br>    <span class="hljs-attribute">transition</span>: filter <span class="hljs-number">0.5s</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><p>按需加载图片 - 上面图片是js for全部异步加载图片 - 改成按需加载</p>
<p>使用<a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/API/Intersection_Observer_API">Intersection Observer API</a>: 提供异步检查目标元素与祖先元素或viewport相交情况变化，可用于：</p>
<ul>
<li>图片懒加载</li>
<li>内容无限滚动</li>
<li>元素曝光率</li>
<li>在用户看见某个区域执行任务</li>
</ul>
<p>过去，检查相交情况需要主线程频繁调用，会有如下情况问题</p>
<figure class="highlight tex"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs tex">假如有一个无限滚动的网页<br>开发者使用了一个第三方库来管理整个页面的广告<br>又用了另外一个库来实现消息盒子和点赞<br>并且页面有很多动画（译注：动画往往意味着较高的性能消耗）<br>两个库都有自己的相交检测程序<br>都运行在主线程里<br>而网站的开发者对这些库的内部实现知之甚少<br>所以并未意识到有什么问题<br>但当用户滚动页面时<br>这些相交检测程序就会在页面滚动回调函数里不停触发调用<br>造成性能问题<br>体验效果让人失望<br></code></pre></td></tr></table></figure>

<p>现在使用观察者API会有一个回调函数，如下情况回调方法会被执行</p>
<ul>
<li>被监听的元素进入或者退出可滚动的祖先元素或视窗时</li>
<li>两个元素的相交部分大小发生变化时</li>
</ul>
<p>观察者API无法提供重叠的像素个数或者具体哪个像素重叠</p>
<p>API使用说明：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">// 所有区域均被交叉观察者看作矩形</span><br><span class="hljs-keyword">let</span> options = &#123;<br>    root: <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">&#x27;#scrollArea&#x27;</span>), <span class="hljs-comment">// 必须是目标元素的父级元素，未指定或者null则为浏览器视窗</span><br>    rootMargin: <span class="hljs-string">&#x27;0px&#x27;</span>, <span class="hljs-comment">// 参数值和css的margin一样(上 右 下 左)，有指定root则可以使用百分比。代表root上下左右外边距作为新的交界线，默认为0</span><br>    threshold: <span class="hljs-number">1.0</span> <span class="hljs-comment">// 取值0-1 或者数组，表示目标元素出现在root可见范围回调，0表示刚要出现，1表示完全出现。数字如[0,1]表示刚刚要出现回调一次，出现完全再次回调。默认0</span><br>&#125;<br><span class="hljs-keyword">let</span> observer = <span class="hljs-keyword">new</span> IntersectionObserver(callback, options);<br><span class="hljs-comment">// 配置目标元素</span><br><span class="hljs-keyword">let</span> target = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">&#x27;#listItem&#x27;</span>);<br>observer.observe(target);<br><span class="hljs-comment">// 配置callback，携带2参数</span><br><span class="hljs-comment">// 在主线程中进行,如果有耗时操作，使用window.requestIdleCallback, 请求浏览器在空闲时候回调</span><br><span class="hljs-keyword">let</span> callback = <span class="hljs-function">(<span class="hljs-params">entries, observer</span>) =&gt;</span> &#123;<br>    <span class="hljs-comment">// entries IntersectionObserverEntry[] 进入该观察对象的目标元素集合</span><br>    <span class="hljs-comment">// observer 观察者对象</span><br>    entries.forEach(<span class="hljs-function"><span class="hljs-params">entry</span> =&gt;</span> &#123;<br>        <span class="hljs-comment">// entry.boundingClientRect DOMRectReadOnly对象，目标元素的边界信息</span><br>        <span class="hljs-comment">// entry.intersectionRatio 交叉比boundingClientRect:intersectionRect，0-1</span><br>        <span class="hljs-comment">// entry.intersectionRect DOMRectReadOnly对象，目标元素与root的相交区域</span><br>        <span class="hljs-comment">// entry.isIntersecting target和root元素的可见性是否发生变化，true表示target在thresholds阈值内</span><br>        <span class="hljs-comment">// entry.rootBounds DOMRectReadOnly对象，root元素的边界信息</span><br>        <span class="hljs-comment">// entry.target 目标元素</span><br>        <span class="hljs-comment">// entry.time 时间戳，表示从观察者创建到交叉触发的时间间隔</span><br>    &#125;)<br>&#125;<br></code></pre></td></tr></table></figure>

<p>实用到图片懒加载</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">if</span> (<span class="hljs-string">&#x27;IntersectionObserver&#x27;</span> <span class="hljs-keyword">in</span> <span class="hljs-built_in">window</span>) &#123;<br>    <span class="hljs-keyword">const</span> callback = <span class="hljs-function">(<span class="hljs-params">entries, observer</span>) =&gt;</span> &#123;<br>        entries.forEach(<span class="hljs-function"><span class="hljs-params">entry</span> =&gt;</span> &#123;<br>            <span class="hljs-keyword">if</span> (entry.isIntersecying) &#123;<br>                loadImages(entry.target);<br>                observer.unobserve(entry.target);<br>            &#125;<br>        &#125;)<br>    &#125;<br>    <span class="hljs-keyword">const</span> observer = <span class="hljs-keyword">new</span> IntersectionObserver(callback); <span class="hljs-comment">// 不知道参数就是视窗</span><br>    imagesToLoad.forEach(<span class="hljs-function">(<span class="hljs-params">img</span>) =&gt;</span> &#123;<br>        observer.observe(img)<br>    &#125;)<br>&#125; <span class="hljs-keyword">else</span> &#123;<br>    imagesToLoad.forEach(<span class="hljs-function">(<span class="hljs-params">img</span>) =&gt;</span> &#123;<br>        loadImages(img);<br>    &#125;)<br>&#125;<br></code></pre></td></tr></table></figure></li>
</ul>
</li>
</ul>
<h1 id="应用框架"><a href="#应用框架" class="headerlink" title="应用框架"></a>应用框架</h1><h2 id="服务器渲染-SSR"><a href="#服务器渲染-SSR" class="headerlink" title="服务器渲染-SSR"></a>服务器渲染-SSR</h2><p>在服务器渲染网页，首次会快，但页面切换时公共组件也会重新获取，会有视觉闪烁，切换相对客户端渲染缓慢</p>
<p>jsp、thymeleaf, 之前在研究院做的网站<code>页面静态化</code>就是服务器渲染。</p>
<h2 id="客户端渲染-CSR"><a href="#客户端渲染-CSR" class="headerlink" title="客户端渲染-CSR"></a>客户端渲染-CSR</h2><p>在客户端渲染网页，首次相对服务器更慢，但页面切换时公共组件保持不变，只更新局部内容，体验更好</p>
<p>用<code>url中的#</code>切换组件</p>
<h2 id="混合渲染"><a href="#混合渲染" class="headerlink" title="混合渲染"></a>混合渲染</h2><p>在服务器渲染网站，之后采用ajax更新局部内容</p>
<h3 id="App-Shell"><a href="#App-Shell" class="headerlink" title="App Shell"></a>App Shell</h3><p>混合渲染的同时还遵循“离线优先”</p>


    </div>
  </div>
  <div class="go-up">
  <a href="#" rel="go-top">
    <i class="fas fa-angle-up"></i>
  </a>
</div>

<script src="/js/bootstrap.min.js"></script>
<script src="/js/TweenMax.min.js"></script>
<script src="/js/resizeable.min.js"></script>
<script src="/js/joinable.js"></script>
<script src="/js/xenon-api.min.js"></script>
<script src="/js/xenon-toggles.min.js"></script>
<script src="/js/xenon-custom.min.js"></script>


<script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>



<script src="/js/lozad.min.js"></script>


</body>

<script src="/js/footer.js"></script>

</html>
